<template>
  <div class="excel-viewer">
    <div v-if="loading" class="loading-container">
      <Loader class="loading-icon" />
      <p>Excel 文件加载中，请稍候...</p>
    </div>

    <div v-else-if="loadError" class="error-container">
      <AlertCircle size="48" />
      <p>{{ loadError }}</p>
      <button class="error-action" @click="reloadExcel">重试</button>
    </div>

    <div v-else>
      <!-- 工具栏 -->
      <div class="excel-toolbar">
        <select v-model="activeSheet" class="sheet-selector">
          <option v-for="(sheet, index) in sheetNames" :key="index" :value="index">
            {{ sheet }}
          </option>
        </select>
      </div>

      <!-- 表格预览区域 -->
      <div class="excel-content" ref="excelContentRef">
        <table class="excel-table" v-if="tableData.length > 0">
          <thead>
            <tr>
              <th></th>
              <!-- 空白角落 -->
              <th v-for="(header, colIndex) in tableHeaders" :key="`header-${colIndex}`">
                {{ header }}
              </th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(row, rowIndex) in tableData" :key="`row-${rowIndex}`">
              <td class="row-header">{{ rowIndex + 1 }}</td>
              <td v-for="(cell, colIndex) in row" :key="`cell-${rowIndex}-${colIndex}`">
                {{ cell }}
              </td>
            </tr>
          </tbody>
        </table>
        <div v-else class="no-data">
          <FileSpreadsheet size="48" />
          <p>没有可显示的数据</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, defineProps, defineEmits, watch } from 'vue'
import { Loader, AlertCircle, FileSpreadsheet } from 'lucide-vue-next'
import * as XLSX from 'xlsx'

const props = defineProps({
  filePath: {
    type: String,
    required: true
  }
})

const emit = defineEmits(['loading-change'])

// 状态变量
const loading = ref(true)
const loadError = ref('')
const workbook = ref<XLSX.WorkBook | null>(null)
const sheetNames = ref<string[]>([])
const activeSheet = ref(0)
const tableData = ref<any[]>([])
const tableHeaders = ref<string[]>([])
const excelContentRef = ref<HTMLDivElement | null>(null)

// 加载Excel文件
const loadExcelFile = async (): void => {
  try {
    loading.value = true
    emit('loading-change', true)

    if (!props.filePath) {
      throw new Error('未提供文件路径')
    }

    // 读取文件
    const response = await fetch(`file://${props.filePath}`)
    const arrayBuffer = await response.arrayBuffer()
    const data = new Uint8Array(arrayBuffer)

    // 解析Excel文件
    workbook.value = XLSX.read(data, { type: 'array' })
    sheetNames.value = workbook.value.SheetNames

    // 默认选择第一个工作表
    if (sheetNames.value.length > 0) {
      activeSheet.value = 0
      loadSheetData(activeSheet.value)
    } else {
      throw new Error('Excel文件不包含任何工作表')
    }

    loading.value = false
    emit('loading-change', false)
  } catch (error) {
    console.error('Excel加载错误:', error)
    loading.value = false
    loadError.value = `Excel加载失败: ${error instanceof Error ? error.message : '未知错误'}`
    emit('loading-change', false)
  }
}

// 加载工作表数据
const loadSheetData = (sheetIndex: number): void => {
  try {
    if (!workbook.value || !sheetNames.value[sheetIndex]) {
      throw new Error('无效的工作表索引')
    }

    const sheetName = sheetNames.value[sheetIndex]
    const worksheet = workbook.value.Sheets[sheetName]

    // 转换为JSON
    const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 })

    // 提取表头(第一行)
    if (jsonData.length > 0) {
      tableHeaders.value = jsonData[0] as string[]
      tableData.value = jsonData.slice(1) as any[]
    } else {
      tableHeaders.value = []
      tableData.value = []
    }
  } catch (error) {
    console.error('工作表数据加载错误:', error)
    tableHeaders.value = []
    tableData.value = []
    loadError.value = `工作表数据加载失败: ${error instanceof Error ? error.message : '未知错误'}`
  }
}

// 监听工作表切换
watch(activeSheet, (newSheetIndex) => {
  loadSheetData(newSheetIndex)
})

// 初始化
onMounted(() => {
  loadExcelFile()
})

// 重新加载Excel
const reloadExcel = (): void => {
  loadError.value = ''
  loading.value = true
  emit('loading-change', true)

  setTimeout(() => {
    loadExcelFile()
  }, 300)
}
</script>

<style scoped>
.excel-viewer {
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  background-color: #ffffff;
  position: relative;
}

.excel-toolbar {
  display: flex;
  padding: 8px 16px;
  background-color: #f0f0f0;
  border-bottom: 1px solid #e0e0e0;
  gap: 8px;
}

.sheet-selector {
  padding: 4px 8px;
  border-radius: 4px;
  border: 1px solid #d0d0d0;
  background-color: #ffffff;
  font-size: 14px;
}

.excel-content {
  flex: 1;
  overflow: auto;
  padding: 8px;
}

.excel-table {
  border-collapse: collapse;
  width: 100%;
  font-size: 14px;
}

.excel-table th,
.excel-table td {
  border: 1px solid #e0e0e0;
  padding: 6px;
  text-align: left;
}

.excel-table th {
  background-color: #f5f5f5;
  font-weight: 500;
  position: sticky;
  top: 0;
  z-index: 1;
}

.excel-table .row-header {
  background-color: #f5f5f5;
  font-weight: 500;
  position: sticky;
  left: 0;
  z-index: 1;
  text-align: center;
}

.excel-table th:first-child {
  z-index: 2; /* 让左上角单元格置于顶部 */
  background-color: #eeeeee;
}

.no-data {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #999;
  gap: 16px;
}

.loading-container,
.error-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  gap: 16px;
  color: var(--theme-text-secondary);
}

.loading-icon {
  animation: spin 1.5s linear infinite;
}

.error-action {
  padding: 8px 16px;
  background-color: var(--theme-primary);
  color: white;
  border: none;
  border-radius: 4px;
  font-weight: 500;
  cursor: pointer;
}

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
</style>
